/*
 * 定义一个简单的隧道协议
 */
#include <core.p4>
#include <v1model.p4>

// 定义自定义报头结构
header myTunnel_t {
    bit<16> dst_id;
}

// 定义元数据结构
struct metadata {
    myTunnel_t myTunnel;
}

// 定义数据包报头集合
struct headers {
    ethernet_t eth;
    ipv4_t ipv4;
    myTunnel_t myTunnel;
}

// 定义解析器状态
parser MyParser(packet_in packet,
                out headers hdr,
                inout metadata meta,
                inout standard_metadata_t standard_metadata) {
    state start {
        packet.extract(hdr.eth);
        transition select(hdr.eth.etherType) {
            0x0800: parse_ipv4;
            default: accept;
        }
    }

    state parse_ipv4 {
        packet.extract(hdr.ipv4);
        transition accept;
    }
}

// 定义Ingress控制逻辑
control MyIngress(inout headers hdr,
                  inout metadata meta,
                  inout standard_metadata_t standard_metadata) {
    // 定义计数器
    counter ingressTunnelCounter;
    counter egressTunnelCounter;

    // 定义表
    table ipv4_lpm {
        key = {
            hdr.ipv4.dstAddr: lpm;
        }
        actions = {
            myTunnel_ingress;
            NoAction;
        }
        size = 1024;
        default_action = NoAction();
    }

    table myTunnel_exact {
        key = {
            hdr.myTunnel.dst_id: exact;
        }
        actions = {
            myTunnel_forward;
            myTunnel_egress;
            NoAction;
        }
        size = 1024;
        default_action = NoAction();
    }

    // 定义动作
    action myTunnel_ingress(bit<16> dst_id) {
        ingressTunnelCounter.increment(1);
        hdr.myTunnel.setValid();
        hdr.myTunnel.dst_id = dst_id;
        standard_metadata.egress_spec = 2; // 转发到交换机端口
    }

    action myTunnel_forward(bit<9> port) {
        standard_metadata.egress_spec = port;
    }

    action myTunnel_egress(bit<48> dstAddr, bit<9> port) {
        egressTunnelCounter.increment(1);
        hdr.myTunnel.setInvalid();
        hdr.eth.dstAddr = dstAddr;
        standard_metadata.egress_spec = port;
    }

    apply {
        if (hdr.ipv4.isValid()) {
            ipv4_lpm.apply();
        }
        if (hdr.myTunnel.isValid()) {
            myTunnel_exact.apply();
        }
    }
}

// 定义Egress控制逻辑
control MyEgress(inout headers hdr,
                 inout metadata meta,
                 inout standard_metadata_t standard_metadata) {
    apply {
        // 这里可以添加Egress阶段的逻辑
    }
}

// 定义Deparser逻辑
control MyDeparser(packet_out packet, in headers hdr) {
    apply {
        packet.emit(hdr.eth);
        if (hdr.myTunnel.isValid()) {
            packet.emit(hdr.myTunnel);
        }
        packet.emit(hdr.ipv4);
    }
}

// 定义V1Model架构
V1Switch(
    MyParser(),
    MyIngress(),
    MyEgress(),
    MyDeparser(),
    NoChecksumVerifier(),
    NoChecksumCalculator()
) main;